﻿using System;
using System.ComponentModel;
using System.Drawing.Design;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Linq;
using MyLib.IO;
using MyLib.Web.Properties;

namespace MyLib.Web.UI {
	/// <summary>
	/// 
	/// </summary>
	[DefaultProperty("FileType")]
	[ToolboxData("<{0}:MyManageFiles runat=server></{0}:ViewFiles>")]
	public class MyManageFiles : CompositeControl, IPostBackDataHandler {
		private int m_fileType;

		private string m_objectId;

		/// <summary>
		/// 
		/// </summary>
		[Bindable(true)]
		[Category("Data")]
		[Localizable(true)]
		public int FileType {
			get {
				return m_fileType;
			}
			set {
				if (m_fileType != value) {
					m_fileType = value;

					// Mark child controls should be recreated.
					ChildControlsCreated = false;
				}
			}
		} // end of FileType.

		/// <summary>
		/// 
		/// </summary>
		[Bindable(true)]
		[Category("Data")]
		[Localizable(true)]
		public string ObjectId {
			get {
				return m_objectId;
			}
			set {
				if (m_objectId != value) {
					m_objectId = value;

					// Mark child controls should be recreated.
					ChildControlsCreated = false;
				}
			}
		} // end of ObjectId.

		/// <summary>
		/// 
		/// </summary>
		public bool CheckEmpty() {
			return CheckEmpty(FileType, ObjectId);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="objectId"></param>
		public bool CheckEmpty(string objectId) {
			return CheckEmpty(FileType, objectId);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="fileType"></param>
		/// <param name="objectId"></param>
		/// <returns></returns>
		public bool CheckEmpty(int fileType, string objectId) {
			// Check if any files will be upladed.
			foreach (var key in Page.Request.Files.AllKeys) {
				if (!key.StartsWith(UniqueID)) {
					// Skip this file.
					continue;
				}

				var postedFile = Page.Request.Files[key];

				if (postedFile == null)
					continue;

				if (postedFile.ContentLength == 0)
					continue;

				return false;
			}

			if (string.IsNullOrEmpty(objectId)) {
				return true;
			}

			// Check if all existing files will be deleted.
			var fp = new FileSystemProvider();

			var checkedFiles = Page.Request.Form[UniqueID + "_CheckFile"];
			var checkedFileIdArray = new string[0];
			if (!string.IsNullOrEmpty(checkedFiles)) {
				checkedFileIdArray = checkedFiles.Split(',');
			}

			var fileIdArray = fp.GetFileObjects(fileType, objectId)
				.Select(fo => fo.Id)
				.ToArray();

			return string.IsNullOrWhiteSpace(
				fileIdArray
				.Except(checkedFileIdArray, StringComparer.OrdinalIgnoreCase)
				.FirstOrDefault()
				);
		}

		/// <summary>
		/// 
		/// </summary>
		public void Save() {
			Save(FileType, ObjectId);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="objectId"></param>
		public void Save(string objectId) {
			Save(FileType, objectId);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="fileType"></param>
		/// <param name="objectId"></param>
		public void Save(int fileType, string objectId) {
			if (string.IsNullOrEmpty(objectId)) {
				throw new ArgumentNullException("objectId");
			}

			var fileCount = 0;
			var fp = new FileSystemProvider();

			// Delete all checked files.
			var checkedFiles = Page.Request.Form[UniqueID + "_CheckFile"];
			var checkedFileIdArray = new string[0];
			if (!string.IsNullOrEmpty(checkedFiles)) {
				checkedFileIdArray = checkedFiles.Split(',');
			}

			foreach (var fileId in checkedFileIdArray) {
				fp.DeleteFileObject(fileId);
			}

			// Save all uploaded files.
			foreach (var key in Page.Request.Files.AllKeys) {
				if (!key.StartsWith(UniqueID)) {
					// Skip this file.
					continue;
				}

				var postedFile = Page.Request.Files[key];

				if (postedFile == null)
					continue;

				if (postedFile.ContentLength == 0)
					continue;

				byte[] content;
				using (var ms = new System.IO.MemoryStream(postedFile.ContentLength)) {
					postedFile.InputStream.CopyTo(ms);

					content = ms.ToArray();

					ms.Close();
				}

				fp.SetFileObject(fileType, objectId,
					System.IO.Path.GetFileName(postedFile.FileName),
					content);

				++fileCount;
			}

			// Mark child controls should be recreated.
			ChildControlsCreated = false;
		}

		/// <summary>
		/// 
		/// </summary>
		[Bindable(true)]
		[Category("Appearance")]
		[DefaultValue("~/File.axd")]
		public string DownloadUrl { get; set; }

		/// <summary>
		/// 
		/// </summary>
		[Bindable(false)]
		public string[] Files { get; set; }

		/// <summary>
		/// 
		/// </summary>
		[Category("Appearance")]
		[Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
		[UrlProperty]
		public string DeleteImageUrl { get; set; }

		/// <summary>
		/// 
		/// </summary>
		[Category("Appearance")]
		[Editor("System.Web.UI.Design.ImageUrlEditor, System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(UITypeEditor))]
		[UrlProperty]
		public string RecoverImageUrl { get; set; }

		/// <summary>
		/// 
		/// </summary>
		protected override HtmlTextWriterTag TagKey {
			get {
				return HtmlTextWriterTag.Ul;
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="e"></param>
		protected override void OnInit(System.EventArgs e) {
			base.OnInit(e);

			Page.RegisterRequiresControlState(this);
			Page.RegisterRequiresPostBack(this);
		}

		/// <summary>
		/// 
		/// </summary>
		protected override void CreateChildControls() {
			Controls.Clear();

			var form = this.Page.Form;
			if ((form != null) && (string.IsNullOrWhiteSpace(form.Enctype))) {
				form.Enctype = "multipart/form-data";
			}

			var fp = new FileSystemProvider();

			var seq = 0;
			if (FileType != 0 && !string.IsNullOrEmpty(ObjectId)) {
				var ofiles = fp.GetFileObjects(FileType, ObjectId);
				var durl = ResolveUrl(DownloadUrl.Trim());

				foreach (var ofile in ofiles) {
					// Skip special file(s).
					if (ofile.Name.StartsWith("__"))
						continue;

					var item = new WebControl(HtmlTextWriterTag.Li);
					item.ID = "Item" + seq;
					item.Attributes["seq"] = Convert.ToString(seq);

					var cbx = new MyInputControl("checkbox");
					cbx.ID = "CheckFile" + seq;
					cbx.Value = ofile.Id;
					cbx.Name = UniqueID + "_CheckFile";
					cbx.Attributes["title"] = Main.file_checked_file_will_be_deleted;
					cbx.Style[HtmlTextWriterStyle.Display] = "none"; // Hide checkbox.

					var lnk = new HyperLink();
					lnk.ID = "DownloadFile" + seq;
					lnk.NavigateUrl = DownloadUrl + "?file_id=" + ofile.Id;
					lnk.ToolTip = string.Format(Main.file_click_to_download, ofile.Name);
					lnk.Text = ofile.Name.AbbreviatedTo();

					var ibt1 = new ImageButton();
					ibt1.ID = "DeleteFile" + seq;
					ibt1.CssClass = "deleteFile";
					ibt1.ImageUrl = DeleteImageUrl;
					ibt1.ImageAlign = ImageAlign.AbsMiddle;
					ibt1.AlternateText = Main.file_remove;
					ibt1.CausesValidation = false;
					ibt1.ToolTip = Main.file_remove + " [" + ofile.Name + "]";
					ibt1.OnClientClick = string.Format("return myManageFiles_checkFile('{0}', {1});", this.ClientID, seq);

					var ibt2 = new ImageButton();
					ibt2.ID = "RecoverFile" + seq;
					ibt2.CssClass = "recoverFile";
					ibt2.ImageUrl = RecoverImageUrl;
					ibt2.ImageAlign = ImageAlign.AbsMiddle;
					ibt2.AlternateText = Main.file_recover;
					ibt2.CausesValidation = false;
					ibt2.ToolTip = Main.file_recover + " [" + ofile.Name + "]";
					ibt2.Style[HtmlTextWriterStyle.Display] = "none"; // Hide button2.
					ibt2.OnClientClick = string.Format("return myManageFiles_uncheckFile('{0}', {1});", this.ClientID, seq);

					item.Controls.Add(cbx);
					item.Controls.Add(lnk);
					item.Controls.Add(ibt1);
					item.Controls.Add(ibt2);

					Controls.Add(item);

					++seq;
				} // end of foreach.
			}

			CreateAdditionChildControls(seq);

			ChildControlsCreated = true;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="seq"></param>
		protected virtual void CreateAdditionChildControls(int seq) {
			// 

			var fitem = new WebControl(HtmlTextWriterTag.Li);
			fitem.ID = "NItem";
			fitem.Attributes["seq"] = Convert.ToString(seq);

			var fcomment = new Literal();
			fcomment.ID = "Comment";
			fcomment.Text = Main.file_new;
			fcomment.Mode = LiteralMode.Encode;

			var uf = new FileUpload();
			uf.ID = string.Format("File_{0}", seq);
			uf.Attributes["seq"] = Convert.ToString(seq);

			// var dp = new TextBox();
			// dp.ID = string.Format("Description_{0}", seq);
			// uf.Attributes["seq"] = Convert.ToString(seq);

			var ibt1 = new ImageButton();
			ibt1.ID = "DeleteNewFile" + seq;
			ibt1.CssClass = "deleteFile";
			ibt1.ImageUrl = DeleteImageUrl;
			ibt1.ImageAlign = ImageAlign.AbsMiddle;
			ibt1.AlternateText = Main.file_remove;
			ibt1.CausesValidation = false;
			ibt1.ToolTip = Main.file_remove;
			ibt1.OnClientClick = string.Format("return myManageFiles_deleteNewFile('{0}', {1});", this.ClientID, seq);

			fitem.Controls.Add(fcomment);
			fitem.Controls.Add(uf);
			// fitem.Controls.Add(dp);
			fitem.Controls.Add(ibt1);
			Controls.Add(fitem);

			// 

			var nfitem = new WebControl(HtmlTextWriterTag.Li);
			nfitem.ID = "None";
			nfitem.CssClass = "none";

			var nf = new HyperLink();
			nf.NavigateUrl = "javascript:void(0);";
			nf.Attributes["onclick"] = string.Format("return myManageFiles_addFile('{0}');", this.ClientID);
			nf.Text = Main.file_add_new;

			nfitem.Controls.Add(nf);
			Controls.Add(nfitem);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="postDataKey"></param>
		/// <param name="postCollection"></param>
		/// <returns></returns>
		public bool LoadPostData(string postDataKey, System.Collections.Specialized.NameValueCollection postCollection) {
			return false;
		}

		/// <summary>
		/// 
		/// </summary>
		public void RaisePostDataChangedEvent() {
			// Do nothing.
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="savedState"></param>
		protected override void LoadControlState(object savedState) {
			object[] stateLastRequest = (object[])savedState;

			// Grab the state for the base class
			// and give it to it.
			object baseState = stateLastRequest[0];
			base.LoadControlState(baseState);

			// Now load this control’s state.
			this.FileType = (int)stateLastRequest[1];
			this.ObjectId = (string)stateLastRequest[2];
			this.DownloadUrl = (string)stateLastRequest[3];
		}

		/// <summary>
		/// 
		/// </summary>
		/// <returns></returns>
		protected override object SaveControlState() {
			// Grab the state for the base control.
			object baseState = base.SaveControlState();

			// Create an array to hold the base control’s state
			// and this control’s state.
			object thisState = new object[] { baseState, FileType, ObjectId, DownloadUrl };
			return thisState;
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="writer"></param>
		protected override void Render(HtmlTextWriter writer) {
			EnsureChildControls();

			base.Render(writer);
		}

		/// <summary>
		/// 
		/// </summary>
		public MyManageFiles() {
			DownloadUrl = "~/File.axd";

			m_fileType = 0;
			m_objectId = null;

			DeleteImageUrl = "~/Common_Images/deleteFile.png";
			RecoverImageUrl = "~/Common_Images/recoverFile.png";
		}
	} // end of ViewFiles.
}
